package com.basic.backend.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.json.JSONException;
import cn.hutool.poi.word.Word07Writer;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.basic.backend.annotation.AuthCheck;
import com.basic.backend.common.BaseResponse;
import com.basic.backend.common.ErrorCode;
import com.basic.backend.common.ResultUtils;
import com.basic.backend.exception.BusinessException;
import com.basic.backend.exception.ThrowUtils;
import com.basic.backend.manager.CosManager;
import com.basic.backend.model.dto.Images.ImageAnalysisDTO;
import com.basic.backend.model.dto.Images.ImagesAddRequest;
import com.basic.backend.model.dto.analysis.ArticleAnalysisDTO;
import com.basic.backend.model.dto.articles.ArticleAddRequest;
import com.basic.backend.model.dto.articles.ArticleQueryRequest;
import com.basic.backend.model.dto.articles.ArticleUpdateRequest;
import com.basic.backend.model.entity.AnalysisResult;
import com.basic.backend.model.entity.ArticleImages;
import com.basic.backend.model.entity.Articles;
import com.basic.backend.model.entity.User;
import com.basic.backend.model.vo.AnalysisResultVO;
import com.basic.backend.model.vo.ArticleVO;
import com.basic.backend.model.vo.UserVO;
import com.basic.backend.service.AnalysisService;
import com.basic.backend.service.ArticleImagesService;
import com.basic.backend.service.ArticlesService;
import com.basic.backend.service.UserService;
import com.basic.backend.service.impl.MessageProducer;
import com.basic.backend.utils.WordParserUtil;
import com.qcloud.cos.exception.CosClientException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.poi.common.usermodel.PictureType;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.Date;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 图文接口
 */
@RestController
@RequestMapping("/articleImages")
@Api(tags = "图文管理")
@Slf4j
public class ArticleImagescontroller {

    @Resource
    private ArticlesService articleService;

    @Resource
    private UserService userService;

    @Resource
    private MessageProducer messageProducer;

    @Resource
    private AnalysisService analysisService;

    @Resource
    private ArticleImagesService articleImagesService;

    @Resource
    private CosManager cosManager;


    @GetMapping("/analysis")
    @ApiOperation(value = "获取图文分析结果", notes = "返回结构化热词列表")
    public BaseResponse<AnalysisResultVO> getAnalysisResult(
            @RequestParam  Long articleId) {

        // 参数校验
        if (articleId == null || articleId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "图文ID不合法");
        }

        // 查询原始数据
        AnalysisResult entity = analysisService.getOne(
                new LambdaQueryWrapper<AnalysisResult>()
                        .eq(AnalysisResult::getArticleId, articleId)
                        .last("LIMIT 1")
        );

        if (entity == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "分析结果不存在");
        }

        // 转换VO
        AnalysisResultVO vo = new AnalysisResultVO();
        BeanUtils.copyProperties(entity, vo);
        // 用户信息处理（添加空值防御）
        Long userId = articleImagesService.getById(vo.getArticleId()).getUserId();
        if (userId == null) {
            log.warn("文章ID: {} 缺少用户ID", articleId);
            vo.setAuthor("未知作者");
        } else {
            UserVO userVO = userService.getUserVO(userId);
            if (userVO != null && userVO.getUserName() != null) {
                vo.setAuthor(userVO.getUserName());
            } else {
                log.warn("用户ID: {} 信息不存在", userId);
                vo.setAuthor("未知作者");
            }
        }

        // 字数统计（防御空内容）
        String content = articleImagesService.getById(articleId).getContent();
        vo.setWordCount(content != null ? content.length() : 0);

        vo.setHotWords(convertHotWords(entity.getHotWords()));
        return ResultUtils.success(vo, "查询成功");
    }

    // JSON字符串转列表
    private List<AnalysisResultVO.HotWord> convertHotWords(String hotWordsJson) {
        try {
            return JSON.parseArray(hotWordsJson, AnalysisResultVO.HotWord.class);
        } catch (JSONException e) {
            log.error("热词解析失败 JSON: {}", hotWordsJson, e);
            return Collections.emptyList();
        }
    }




    /**
     * 创建图文
     *
     * @param request     图文请求参数
     * @return 图文ID
     */
    @PostMapping("/add")
    @ApiOperation(value = "创建图文（COS存储版）")
    public BaseResponse<Long> createArticle(
            @RequestParam String title,
            @RequestParam String content,
            @RequestParam("images") MultipartFile[] images,
            HttpServletRequest request) {

        // 1. 基础校验
        if (images == null || images.length == 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "至少需要一张图片");
        }

        // 2. 获取登录用户
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }

        // 3. 保存文章基础信息
        ArticleImages imageRecord = new ArticleImages();
        imageRecord.setUserId(loginUser.getId());
        imageRecord.setTitle(title);
        imageRecord.setContent(content);
        imageRecord.setImages(""); // 先存空路径
        articleImagesService.save(imageRecord);
        List<String> imageUrls = new ArrayList<>();
        try {
            // 4. 处理图片上传
            String cleanTitle = title.replaceAll("[^\\w\\d-]", "_"); // 清理特殊字符
            cleanTitle = cleanTitle.substring(0, Math.min(cleanTitle.length(), 50)); // 限制长度

            for (int i = 0; i < images.length; i++) {
                MultipartFile image = images[i];

                // 生成文件名：标题_序号.后缀
                String suffix = FileUtil.getSuffix(image.getOriginalFilename());
                String fileName = String.format("%s_%d.%s", cleanTitle, i+1, suffix);

                // 生成COS路径：articles/{文章ID}/{文件名}
                String fileKey = String.format("articles/%d/%s", imageRecord.getArticleId(), fileName);

                // 上传到COS
                File tempFile = convertToTempFile(image);
                cosManager.putObject(fileKey, tempFile);
                tempFile.delete();

                // 收集访问URL
                String url = String.format("https://%s.cos.%s.myqcloud.com/%s",
                        cosManager.getBucketName(),
                        cosManager.getRegion(),
                        fileKey);
                imageUrls.add(url);
            }
            imageRecord.setArticleId(imageRecord.getArticleId());

            // 5. 保存图片记录
            imageRecord.setImages(String.join(",", imageUrls)); // 或用JSON格式存储
            boolean imagesSaved = articleImagesService.updateById(imageRecord);

            if (!imagesSaved) {
                deleteCosImages(imageUrls); // 自定义方法删除COS文件
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "图片记录保存失败");
            }
            ImageAnalysisDTO analysisDTO = new ImageAnalysisDTO();
            analysisDTO.setArticleId(imageRecord.getArticleId());
            analysisDTO.setImageUrls(imageRecord.getImages());
            analysisDTO.setTitle(title);
            analysisDTO.setContent(content);
            analysisDTO.setPublishTime(LocalDateTime.now().toString());

            // 4. 发送分析任务到消息队列
            messageProducer.sendImageAnalysisTask(analysisDTO);
            return ResultUtils.success(imageRecord.getArticleId(),"");
        } catch (Exception e) {
            // 异常处理：删除已上传的COS文件和文章记录
            deleteCosImages(imageUrls);
            articleService.removeById(imageRecord.getArticleId());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "图文创建失败");
        }
    }

//-- 辅助方法 --//

    /**
     * 转换为临时文件
     */
    private File convertToTempFile(MultipartFile file) throws IOException {
        String prefix = "tmp-img-" + System.currentTimeMillis();
        String suffix = "." + FileUtil.getSuffix(file.getOriginalFilename());
        File tempFile = File.createTempFile(prefix, suffix);
        file.transferTo(tempFile);
        return tempFile;
    }

    /**
     * 删除COS中的图片
     */
    private void deleteCosImages(List<String> urls) {
        urls.stream()
                .filter(url -> url != null && !url.isEmpty())
                .forEach(url -> {
                    // 使用正则精确匹配路径
                    Pattern pattern = Pattern.compile("https://[^/]+/(.*)");
                    Matcher matcher = pattern.matcher(url);
                    if (matcher.find()) {
                        String fileKey = matcher.group(1);
                        try {
                            cosManager.deleteObject(fileKey);
                            log.info("成功删除文件: {}", fileKey);
                        } catch (CosClientException e) {
                            log.error("文件删除失败: {}", fileKey, e);
                        }
                    } else {
                        log.warn("无效的COS URL格式: {}", url);
                    }
                });
    }






    @PostMapping("/page")
    @ApiOperation("图文分页查询")
    public BaseResponse<Page<ArticleVO>> getArticlePage(
            @RequestBody ArticleQueryRequest request,
            HttpServletRequest httpRequest) {

        // 权限处理
        Long userId = userService.getUserIdByToken(httpRequest);
        if (!userService.isAdmin(httpRequest)) {
            request.setUserId(userId);
        }
        // 分页查询
        Page<ArticleVO> result = articleImagesService.getArticleImagesPage(request,httpRequest);


        return ResultUtils.success(result, "");
    }



    @DeleteMapping("/delete")
    @ApiOperation(value = "删除图文", notes = "根据图文ID删除图文")
    public BaseResponse<Boolean> deleteArticle(@RequestParam("id") Long articleId,
                                               HttpServletRequest request) {
        // 参数校验
        if (articleId == null || articleId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "图文ID不合法");
        }

        // 获取当前登录用户
        Long userId = userService.getUserIdByToken(request);
        // 删除图文
        boolean result = articleImagesService.removeById(articleId);
        return result ? ResultUtils.success(true, "删除成功") : ResultUtils.error(ErrorCode.OPERATION_ERROR, "删除失败");
    }

    @PostMapping("/update")
    @ApiOperation(value = "更新图文信息", notes = "可更新标题、内容、状态及图片")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Boolean> updateArticle(
            @RequestParam Long articleId,
            @RequestParam(required = false) String title,
            @RequestParam(required = false) String content,
            @RequestParam(required = false) String status,
            @RequestParam(value = "images", required = false) MultipartFile[] newImages,
            HttpServletRequest request) {

        // 1. 参数校验
        if (articleId == null || articleId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "图文ID不合法");
        }

        // 2. 权限验证
        User loginUser = userService.getLoginUser(request);
        ArticleImages existingArticle = articleImagesService.getById(articleId);
        if (existingArticle == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "图文不存在");
        }
        if (!existingArticle.getUserId().equals(loginUser.getId()) && !userService.isAdmin(request)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }

        // 3. 准备更新实体
        ArticleImages updateEntity = new ArticleImages();
        updateEntity.setArticleId(articleId);
        if (StringUtils.isNotBlank(title)) updateEntity.setTitle(title);
        if (StringUtils.isNotBlank(content)) updateEntity.setContent(content);
        if (StringUtils.isNotBlank(status)) updateEntity.setStatus(status);

        // 4. 处理图片更新
        List<String> newImageUrls = new ArrayList<>();
        try {
            if (newImages != null && newImages.length > 0) {
                String cleanTitle = (title != null ? title : existingArticle.getTitle())
                        .replaceAll("[^\\w\\d-]", "_")
                        .substring(0, Math.min(50, title.length()));

                // 直接上传新图片（不处理旧文件）
                for (int i = 0; i < newImages.length; i++) {
                    MultipartFile image = newImages[i];
                    String suffix = FileUtil.getSuffix(image.getOriginalFilename());
                    String fileName = String.format("%s_%d.%s", cleanTitle, i+1, suffix);
                    String fileKey = String.format("articles/%d/%s", articleId, fileName);

                    File tempFile = convertToTempFile(image);
                    cosManager.putObject(fileKey, tempFile);
                    tempFile.delete();

                    newImageUrls.add(String.format("https://%s.cos.%s.myqcloud.com/%s",
                            cosManager.getBucketName(),
                            cosManager.getRegion(),
                            fileKey));
                }
                updateEntity.setImages(String.join(",", newImageUrls));
            }
            log.info("成功上传新图片: {}", newImageUrls);
            // 5. 强制更新数据库
            boolean updateResult = articleImagesService.updateById(updateEntity);
            if (!updateResult) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR);
            }

            // 6. 发送分析任务（保持原有逻辑）
            ImageAnalysisDTO analysisDTO = new ImageAnalysisDTO();
            BeanUtils.copyProperties(existingArticle, analysisDTO);
            analysisDTO.setImageUrls(String.join(",", newImageUrls));
            messageProducer.sendImageAnalysisTask(analysisDTO);

            return ResultUtils.success(true, "更新成功");

        } catch (Exception e) {
            // 仅打印日志不进行任何文件删除操作
            log.error("更新操作异常，已保留所有COS文件", e);
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "数据库更新失败: " + e.getMessage());
        }
    }


    @PostMapping("/info")
    @ApiOperation(value = "获取图文详情", notes = "根据图文ID获取图文详情")
    public BaseResponse<ArticleVO> getArticleInfo(@RequestParam Long articleId, HttpServletRequest request) {
        if (articleId == null || articleId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "图文ID不合法");
        }
        ArticleImages article = articleImagesService.getById(articleId);
        if (article == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "图文不存在");
        }
        ArticleVO articleVO = new ArticleVO();
        BeanUtils.copyProperties(article, articleVO);
        UserVO author = userService.getUserVO(userService.getById(article.getUserId()));
        articleVO.setAuthor(author);
        articleVO.setImages(Arrays.asList(article.getImages().split(",")));
        return ResultUtils.success(articleVO,"");
    }

    @PostMapping("/deleteBatch")
    @ApiOperation("批量删除图文")
    @AuthCheck(mustRole = "user")
    public BaseResponse<Boolean> deleteBatch(@RequestBody List<Long> articleIds, HttpServletRequest request) {
        if (articleIds == null || articleIds.isEmpty()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }

        // 获取当前登录用户
        Long userId = userService.getUserIdByToken(request);
        if (!userService.isAdmin(request) && !userId.equals(userService.getLoginUser(request).getId())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }

        // 删除文章
        boolean result = articleImagesService.removeByIds(articleIds);
        return result ? ResultUtils.success(true, "删除成功") : ResultUtils.error(ErrorCode.OPERATION_ERROR, "删除失败");
    }

    @PostMapping("/uploadWordArticles")
    @ApiOperation(value = "批量上传Word文档生成图文",
            notes = "支持多个.docx文件，文件名作为标题，内容作为正文，图片自动上传")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Integer> uploadWordArticles(
            @RequestParam("files") MultipartFile[] wordFiles,
            HttpServletRequest request) {

        if (wordFiles == null || wordFiles.length == 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "至少上传一个Word文件");
        }

        User loginUser = userService.getLoginUser(request);
        int successCount = 0;

        // 图片类型映射表
        Map<Integer, String> pictureExtensions = new HashMap<Integer, String>() {{
            put(PictureType.JPEG.getOoxmlId(), ".jpg");
            put(PictureType.PNG.getOoxmlId(), ".png");
            put(PictureType.GIF.getOoxmlId(), ".gif");
            put(PictureType.BMP.getOoxmlId(), ".bmp");
        }};

        for (MultipartFile file : wordFiles) {
            Long articleId = null;
            List<String> imageUrls = new ArrayList<>();
            List<File> tempFiles = new ArrayList<>(); // 新增临时文件列表

            try (XWPFDocument doc = new XWPFDocument(file.getInputStream())) {
                // 1. 解析基础信息
                String title = FilenameUtils.getBaseName(file.getOriginalFilename());
                String content = doc.getParagraphs().stream()
                        .map(XWPFParagraph::getText)
                        .collect(Collectors.joining("\n"))
                        .trim();

                // 2. 创建初始记录（立即获取ID）
                ArticleImages article = new ArticleImages();
                article.setUserId(loginUser.getId());
                article.setTitle(title);
                article.setContent(content);
                article.setImages(""); // 初始化为空字符串
                articleImagesService.save(article);
                articleId = article.getArticleId();

                // 3. 处理图片上传（增加数据校验）
                List<String> uploadedUrls = new ArrayList<>();
                int imgIndex = 1;

                for (XWPFPictureData picture : doc.getAllPictures()) {
                    File tempFile = null;
                    try {
                        // 创建临时文件
                        tempFile = File.createTempFile("cos_", ".tmp");
                        tempFiles.add(tempFile);

                        // 写入文件并验证
                        byte[] originalData = picture.getData();
                        Files.write(tempFile.toPath(), originalData);
                        byte[] verifiedData = Files.readAllBytes(tempFile.toPath());

                        if (verifiedData.length != originalData.length) {
                            throw new IOException(String.format(
                                    "数据校验失败! 原始长度:%d 实际长度:%d",
                                    originalData.length, verifiedData.length));
                        }

                        // 上传到COS
                        String extension = pictureExtensions.getOrDefault(
                                picture.getPictureType(), ".dat");
                        String fileName = String.format("___%d%s", imgIndex++, extension);
                        String fileKey = String.format("articles/%d/%s", articleId, fileName);

                        cosManager.putObject(fileKey, tempFile); // 改为文件上传

                        // 生成URL
                        String url = String.format("https://%s.cos.%s.myqcloud.com/%s",
                                cosManager.getBucketName(),
                                cosManager.getRegion(),
                                fileKey);
                        uploadedUrls.add(url);
                    } finally {
                        // 确保删除临时文件
                        if (tempFile != null && tempFile.exists()) {
                            try {
                                Files.delete(tempFile.toPath());
                            } catch (IOException ex) {
                                log.warn("临时文件删除失败: {}", tempFile.getAbsolutePath(), ex);
                            }
                        }
                    }
                }

                // 4. 更新图片字段
                if (!uploadedUrls.isEmpty()) {
                    article.setImages(String.join(",", uploadedUrls));
                    if (!articleImagesService.updateById(article)) {
                        throw new BusinessException(ErrorCode.OPERATION_ERROR);
                    }
                } else {
                    log.info("文档未包含有效图片: {}", file.getOriginalFilename());
                    article.setImages("no_images");
                    articleImagesService.updateById(article);
                }

                // 5. 发送分析任务
                ImageAnalysisDTO dto = new ImageAnalysisDTO();
                dto.setArticleId(articleId);
                dto.setTitle(article.getTitle());
                dto.setContent(article.getContent());
                dto.setImageUrls(article.getImages());
                messageProducer.sendImageAnalysisTask(dto);

                successCount++;
            } catch (Exception e) {
                // 清理所有临时文件
                tempFiles.forEach(f -> {
                    try {
                        if (f.exists()) Files.delete(f.toPath());
                    } catch (IOException ex) {
                        log.warn("临时文件清理失败: {}", f.getAbsolutePath(), ex);
                    }
                });

                // 错误处理
                handleUploadError(file.getOriginalFilename(), articleId, imageUrls, e);
            }
        }
        return ResultUtils.success(successCount, "成功处理 " + successCount + " 个文件");
    }

    // 错误处理方法保持不变
    private void handleUploadError(String filename, Long articleId,
                                   List<String> uploadedUrls, Exception e) {
        log.error("文件处理失败: {}", filename, e);

        // 清理COS文件
        if (!uploadedUrls.isEmpty()) {
            uploadedUrls.forEach(url -> {
                try {
                    String fileKey = url.substring(url.indexOf("/", 8) + 1);
                    cosManager.deleteObject(fileKey);
                } catch (Exception ex) {
                    log.warn("COS文件清理失败: {}", url, ex);
                }
            });
        }

        // 删除数据库记录
        if (articleId != null) {
            articleImagesService.removeById(articleId);
        }

        throw new BusinessException(ErrorCode.OPERATION_ERROR,
                String.format("文件[%s]处理失败: %s", filename,
                        e.getMessage().contains("数据校验失败") ?
                                "文件传输不完整，请重新上传" : e.getMessage()));
    }
}
